package com.jdk.learn.base;

/**
 * Created by ricky
 * on 2018/2/28.
-------------------------------
 关于10进制转二进制
 十进制:3
 二进制:0000 0101
 如果是1的话，则记一次有效位,可以做2的幂方
 从末尾一次幂方数为0,1,2,3....
 上述的十进制结果为: (2的0次方)+(2的2次方)=1+4=5

 (java中十进制-3表示成功二进制会有32位，【11111111111111111111111111111101】)
 ---------------------------------------------------
 正数:3
 原码:0000 0101
 反码:0000 0101
 补码:0000 0101
 正数的原码反码 补码都一样

 负数:-3
 原码:1111 1101
 反码:1000 0010
 补码:1000 0011
 反码是符号位不变，其他位取反
 补码----------,反码+1

 ------------------------------
    计算机中是按补码进行计算的
 ------------------------------

 Java位运算
    a=3 b=5
 二进制为011   和101
        011
        101

 含义		 Java
 按位与        a & b
    相同位的两个数字都为1，则为1；若有一个不为1，则为0。

    结果:001 = 1

 按位或        a | b
    相同位只要一个为1即为1。

    结果:111 = 4+2+1=7

 按位异或	      a ^ b
    相同位不同则为1，相同则为0。

    结果: 110 = 4+2=6

 按位取反	     	~a (a=3)
    取反:0变1 1变0
    0000 0011
    结果:1111 1100(~a的结果的原码)

    -----计算十进制
    求1111 1100的补码，取反(0000 0011)+1(逢2进1)
    (保留符号位)
    1000 0100(补码)
    结果:-4


 带符号左移	    	a << b
 0000 0011
 左移5位
 0110 0000 = 2*5 + 2*6 = 32 + 64

 带符号右移		a >> b
 0000 0011
 右移5位
 0000 0000 = 0

 无符号右移		a>>> b
 1000 0011
 右移5位
 1000 0000

 */
public class YunSuan {
    public static void main(String[] args) {
//        System.out.println(test(3,5));

        int a=3;
        int b=5;
        System.out.println(Integer.toBinaryString(~46));
        System.out.println(~46);
        //与运算  同为1 则为1
        System.out.println("与运算a&b:"+ (a&b));
        //或运算  只要有1 则为1
        System.out.println("或运算a|b:"+ (a|b));
        // 异或运算  位不同则为1
        System.out.println("异或运算a^b:"+ (a^b));
        // 非运算
        System.out.println("取反运算~a:"+ (~a));
        System.out.println("取反运算~b:"+ (~b));
        System.out.println("左移运算a<<b:"+ (a<<b));
        System.out.println("右移运算a>>b:"+ (a>>b));
        System.out.println("右移运算a>>>b:"+ (a>>>b));
        System.out.println("------------------------------------");
        System.out.println("----"+Integer.toBinaryString(4));
        System.out.println(Integer.toBinaryString(-4));
        System.out.println("------------------------------------");
        System.out.println(Integer.toBinaryString(-3));
        System.out.println("11111111111111111111111111111101".length());
//        System.out.println("无符号左移运算a<<<b:"+ (a<<<b));
//        test(5,8);

        System.out.println(Integer.toBinaryString(-1));
        //算数右移：低位溢出，符号位不变，并用符号位补溢出的高位
        //算数左移：符号位不变，低位补0
        System.out.println(-1>>2);
        System.out.println(-1<<2);
        System.out.println();
        System.out.print("~(-3)=");
        System.out.println(~(-3));
        System.out.print("-3&2=");
        System.out.println(-3&2);
        System.out.print("-3|2=");
        System.out.println(-3|2);
        System.out.print("-3^2=");
        System.out.println(-3^2);
        System.out.print("-3<<2=");
        System.out.println(-3<<2);
        System.out.print("-3>>2=");
        System.out.println(-3>>2);
    }

    /**
     * 求和
     * 以a=3和b=5为例
     a:11,b:101

     a:110,b:10

     a:100,b:100

     a:0,b:1000

     a:1000,b:0


     =================
     等价于
      011
     +101
     ----
     1000
     逢2进1
     * @param a
     * @param b
     * @return
     */
    public static int test(int a, int b) {
        System.out.println();
        System.out.print("a:"+Integer.toBinaryString(a));
        System.out.println(",b:"+Integer.toBinaryString(b));
        if(b == 0) return a;
        int c = a ^ b;//异或运算  不同则是1
        int d = (a & b) << 1;//与运算 都是1则是1  然后左移一位(判断是否需要进位)
        return test(c, d);
    }
}
